package com.stm.bi.repository.report;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.stm.bi.dto.query.SubjectCategoryListQry;
import com.stm.bi.dto.vo.SubjectCategoryVO;
import com.stm.bi.repository.report.dataobject.SubjectCategoryDO;
import com.stm.bi.repository.report.mapper.SubjectCategoryMapper;
import com.stm.framework.core.util.StringUtil;
import com.stm.framework.repository.BaseRepository;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 科目分类-仓储
 *
 * @author qinyongjie
 * @date 2025-05-22
 */
@Repository
public class SubjectCategoryRepository extends BaseRepository<SubjectCategoryMapper, SubjectCategoryDO, SubjectCategoryVO> {


    //region 主方法区

    /**
     * 查询所有分类
     */
    public List<SubjectCategoryDO> selectAllCategories(String name) {
        if (StringUtil.isEmpty(name)) {
            // 如果没有搜索条件，返回所有分类
            LambdaQueryWrapper<SubjectCategoryDO> queryWrapper = Wrappers.<SubjectCategoryDO>lambdaQuery()
                    .orderByAsc(SubjectCategoryDO::getCreateDt)
                    .orderByAsc(SubjectCategoryDO::getParentId)
                    .orderByAsc(SubjectCategoryDO::getId);
            return this.baseMapper.selectList(queryWrapper);
        }

        // 有搜索条件时，需要递归查询相关节点
        return selectCategoriesWithSearch(name);
    }
    //endregion


    //region 私有方法区
    // 根据名称搜索并递归查询相关节点
    private List<SubjectCategoryDO> selectCategoriesWithSearch(String name) {
        // 1. 先查找所有名称匹配的节点
        LambdaQueryWrapper<SubjectCategoryDO> matchWrapper = Wrappers.<SubjectCategoryDO>lambdaQuery().like(SubjectCategoryDO::getName, name);
        List<SubjectCategoryDO> matchedCategories = this.baseMapper.selectList(matchWrapper);

        if (CollectionUtils.isEmpty(matchedCategories)) {
            return new ArrayList<>();
        }

        // 2. 收集所有相关的分类ID（包括父节点和子节点）
        Set<Long> allRelatedIds = new HashSet<>();

        for (SubjectCategoryDO matched : matchedCategories) {
            // 添加匹配节点本身
            allRelatedIds.add(matched.getId());

            // 添加所有父节点ID
            addParentIds(matched.getPath(), allRelatedIds);

            // 添加所有子节点ID
//            addChildrenIds(matched.getId(), allRelatedIds);
        }

        // 3. 根据收集到的ID查询所有相关分类
        if (allRelatedIds.isEmpty()) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<SubjectCategoryDO> resultWrapper = Wrappers.<SubjectCategoryDO>lambdaQuery()
                .in(SubjectCategoryDO::getId, allRelatedIds)
                .orderByAsc(SubjectCategoryDO::getCreateDt)
                .orderByAsc(SubjectCategoryDO::getParentId)
                .orderByAsc(SubjectCategoryDO::getId);

        return this.baseMapper.selectList(resultWrapper);
    }

    // 从路径中提取所有父节点ID
    private void addParentIds(String path, Set<Long> allRelatedIds) {
        if (StringUtil.isEmpty(path)) {
            return;
        }

        String[] pathIds = path.split(",");
        for (String pathId : pathIds) {
            try {
                Long id = Long.parseLong(pathId.trim());
                if (id > 0) { // 排除根节点0
                    allRelatedIds.add(id);
                }
            } catch (NumberFormatException e) {
                // 忽略无效的ID
            }
        }
    }

    // 递归查询所有子节点ID
    private void addChildrenIds(Long parentId, Set<Long> allRelatedIds) {
        // 查询直接子节点
        LambdaQueryWrapper<SubjectCategoryDO> childWrapper = Wrappers.<SubjectCategoryDO>lambdaQuery()
                .eq(SubjectCategoryDO::getParentId, parentId)
                .select(SubjectCategoryDO::getId);

        List<SubjectCategoryDO> children = this.baseMapper.selectList(childWrapper);

        for (SubjectCategoryDO child : children) {
            allRelatedIds.add(child.getId());
            // 递归查询子节点的子节点
            addChildrenIds(child.getId(), allRelatedIds);
        }
    }

    // 根据分类ID递归查询所有子分类ID（包括自身）
    public List<Long> selectAllSubCategoryIds(Long categoryId) {
        if (categoryId == null) {
            return List.of();
        }

        // 查询当前分类信息
        SubjectCategoryDO currentCategory = this.getById(categoryId);
        if (currentCategory == null) {
            return List.of();
        }

        // 构建当前分类的路径前缀，用于查找所有子分类
        String currentPath = currentCategory.getPath();
        String pathPrefix;

        if (StringUtil.isEmpty(currentPath)) {
            // 如果当前分类没有路径，说明是根分类，路径前缀为当前ID
            pathPrefix = categoryId.toString();
        } else {
            // 如果有路径，拼接当前ID作为路径前缀
            pathPrefix = currentPath + "," + categoryId;
        }

        // 查询所有路径以当前路径前缀开头的分类（即所有子分类）
        LambdaQueryWrapper<SubjectCategoryDO> queryWrapper = Wrappers.<SubjectCategoryDO>lambdaQuery()
                .like(SubjectCategoryDO::getPath, pathPrefix)
                .select(SubjectCategoryDO::getId);

        List<SubjectCategoryDO> subCategories = this.baseMapper.selectList(queryWrapper);

        // 提取所有子分类ID，并加上当前分类ID
        List<Long> allCategoryIds = subCategories.stream()
                .map(SubjectCategoryDO::getId)
                .collect(Collectors.toList());

        // 添加当前分类ID
        allCategoryIds.add(categoryId);

        return allCategoryIds;
    }

    private LambdaQueryWrapper buildeQueryWrapper(SubjectCategoryListQry subjectCategoryListQry) {
        LambdaQueryWrapper<SubjectCategoryDO> queryWrapper = Wrappers.<SubjectCategoryDO>lambdaQuery()
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getId()), SubjectCategoryDO::getId, subjectCategoryListQry.getId())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getOrgId()), SubjectCategoryDO::getOrgId, subjectCategoryListQry.getOrgId())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getName()), SubjectCategoryDO::getName, subjectCategoryListQry.getName())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getParentId()), SubjectCategoryDO::getParentId, subjectCategoryListQry.getParentId())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getDefinition()), SubjectCategoryDO::getDefinition, subjectCategoryListQry.getDefinition())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getPath()), SubjectCategoryDO::getPath, subjectCategoryListQry.getPath())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getCreator()), SubjectCategoryDO::getCreator, subjectCategoryListQry.getCreator())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getCreatorId()), SubjectCategoryDO::getCreatorId, subjectCategoryListQry.getCreatorId())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getCreateDt()), SubjectCategoryDO::getCreateDt, subjectCategoryListQry.getCreateDt())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getLastUpdater()), SubjectCategoryDO::getLastUpdater, subjectCategoryListQry.getLastUpdater())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getLastUpdaterId()), SubjectCategoryDO::getLastUpdaterId, subjectCategoryListQry.getLastUpdaterId())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getLastUpdateDt()), SubjectCategoryDO::getLastUpdateDt, subjectCategoryListQry.getLastUpdateDt())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getDeleted()), SubjectCategoryDO::getDeleted, subjectCategoryListQry.getDeleted())
                .eq(StringUtil.isNotEmpty(subjectCategoryListQry.getRemark()), SubjectCategoryDO::getRemark, subjectCategoryListQry.getRemark());
        return queryWrapper;
    }
    //endregion

}
